#include "paral_py.h"

void init_paral_py_context(struct paral_py_context *ctx, const char *filename)
{
    assert(ctx != NULL);

    // 只对一开始的部分进行初始化
    ctx->identifier_str = "";
    ctx->double_num_val = 0;
    ctx->long_num_val = 0;
    ctx->tab_size = 0;
    ctx->line_num = 0;

    ctx->file_name = filename;

    ctx->fd = fopen(filename, "r");

    assert(ctx->fd != NULL);

    // 初始化所有保留字
    ctx->remain_str_arr.push_back("False");
    ctx->remain_str_arr.push_back("None");
    ctx->remain_str_arr.push_back("True");
    ctx->remain_str_arr.push_back("and");
    ctx->remain_str_arr.push_back("as");
    ctx->remain_str_arr.push_back("assert");
    ctx->remain_str_arr.push_back("break");
    ctx->remain_str_arr.push_back("class");
    ctx->remain_str_arr.push_back("continue");
    ctx->remain_str_arr.push_back("def");
    ctx->remain_str_arr.push_back("return");
    ctx->remain_str_arr.push_back("del");
    ctx->remain_str_arr.push_back("elif");
    ctx->remain_str_arr.push_back("if");
    ctx->remain_str_arr.push_back("else");
    ctx->remain_str_arr.push_back("except");
    ctx->remain_str_arr.push_back("finally");
    ctx->remain_str_arr.push_back("try");
    ctx->remain_str_arr.push_back("for");
    ctx->remain_str_arr.push_back("in");
    ctx->remain_str_arr.push_back("from");
    ctx->remain_str_arr.push_back("import");
    ctx->remain_str_arr.push_back("global");
    ctx->remain_str_arr.push_back("is");
    ctx->remain_str_arr.push_back("lambda");
    ctx->remain_str_arr.push_back("nonlocal");
    ctx->remain_str_arr.push_back("not");
    ctx->remain_str_arr.push_back("or");
    ctx->remain_str_arr.push_back("pass");
    ctx->remain_str_arr.push_back("raise");
    ctx->remain_str_arr.push_back("while");
    ctx->remain_str_arr.push_back("with");
    ctx->remain_str_arr.push_back("yield");
}

char get_char(struct paral_py_context *ctx)
{
    return fgetc(ctx->fd);
}

void print_token_type(int type)
{
    if (type == tok_def)
    {
        printf("tok_def");
    }
    else if (type == tok_eof)
    {
        printf("tok_eof");
    }
    else if (type == tok_identifier)
    {
        printf("tok_identifier");
    }
    else if (type == tok_seq_comm_assoca_def_type)
    {
        printf("tok_seq_comm_assoca_def_type");
    }
    else if (type == tok_seq_def_type)
    {
        printf("tok_seq_def_type");
    }
    else if (type == tok_input_central_paral_type)
    {
        printf("tok_input_central_paral_type");
    }
    else if (type == tok_iter_central_paral_type)
    {
        printf("tok_iter_central_paral_type");
    }
    else if (type == tok_place_holder)
    {
        printf("tok_place_holder");
    }
    else if (type == tok_tab)
    {
        printf("tok_tab");
    }
    else if (type == tok_double)
    {
        printf("tok_double");
    }
    else if (type == tok_int)
    {
        printf("tok_int");
    }
    else if (type == tok_python_remain)
    {
        printf("tok_python_remain");
    }
    else
    {
        printf("%c", type);
    }
}

void print_current_token(struct paral_py_context *ctx, int type)
{
    if (type == tok_def)
    {
        printf("tok_def");
    }
    else if (type == tok_eof)
    {
        printf("tok_eof");
    }
    else if (type == tok_identifier)
    {
        printf("tok_identifier:%s", ctx->identifier_str.c_str());
    }
    else if (type == tok_seq_comm_assoca_def_type)
    {
        printf("tok_seq_comm_assoca_def_type");
    }
    else if (type == tok_seq_def_type)
    {
        printf("tok_seq_def_type");
    }
    else if (type == tok_input_central_paral_type)
    {
        printf("tok_input_central_paral_type");
    }
    else if (type == tok_iter_central_paral_type)
    {
        printf("tok_iter_central_paral_type");
    }
    else if (type == tok_place_holder)
    {
        printf("tok_place_holder");
    }
    else if (type == tok_tab)
    {
        printf("tok_tab:%d", ctx->tab_size);
    }
    else if (type == tok_double)
    {
        printf("tok_double:%f", ctx->double_num_val);
    }
    else if (type == tok_int)
    {
        printf("tok_int:%ld", ctx->long_num_val);
    }
    else if (type == tok_python_remain)
    {
        printf("tok_python_remain:%s", ctx->identifier_str.c_str());
    }
    else
    {
        printf("%c", type);
    }
}

// 打印寒暑表表项
void print_function_item(struct function_table_item *item)
{
    print_token_type(item->function_type);
    printf(",%d,%d", item->function_begin_line, item->function_end_line);
}

// 打印函数表
void print_function_table(struct paral_py_context *ctx)
{
    assert(ctx!= NULL);
    std::map<std::string, struct function_table_item>::iterator iter;
    
    printf("function_table=====:\n");

    for (iter=ctx->fun_table.begin();iter!= ctx->fun_table.end();iter++)
    {
        printf("%s,",iter->first.c_str());
        print_function_item(&(iter->second));
        printf("\n");
    }

    printf("=====\n");
}

void add_item_to_function_table(struct paral_py_context *ctx, std::string fun_name, int type,
    int start_line, int end_line){
    assert(ctx != NULL);
    
    struct function_table_item item;
    // 初始化
    memset(&item, 0, sizeof(struct function_table_item));

    item.function_type = type;
    item.function_begin_line = start_line;
    item.function_end_line = end_line;

    // 查看这个函数之前有没有被登记
    if(ctx->fun_table.count(fun_name)==0){
        printf("find function %s\n", fun_name.c_str());
        ctx->fun_table.insert(std::make_pair(fun_name, item));
        // (ctx->fun_table)[fun_name] = item;
    }else{
        printf("function %s is defined twice\n", fun_name.c_str());
        exit(-1);
    }
}

void print_import_code_arr(struct paral_py_context* ctx){
    printf("import_code_arr=====:\n");

    int i;
    for(i = 0; i < ctx->import_code_str_arr.size(); i++){
        printf("%s\n", ctx->import_code_str_arr[i].c_str());
    }

    printf("=====\n");
}

// 获取文件对应行的代码
std::string get_code_by_line(std::string file_name, int start_line, int end_line){
    assert(start_line <= end_line);

    std::ifstream in(file_name);

    int line_num = 0;
    std::string line;
    std::string return_str = "";

    // 一行一行读
    while(getline(in, line)){
        if(line_num >= start_line && line_num <= end_line){
            return_str = return_str + line + "\n";
        }

        line_num++;
    }

    // 读完之后返回
    return return_str;
}

std::string get_key_str_of_result(std::string result_str){
    
    if(result_str.find("result[" == 0)){
        
        // 首先读到[
        char cur_char = result_str[0];
        int cur_char_index = 0;
        std::string return_str = "";

        while(cur_char != '['){
            cur_char_index++;
            cur_char = result_str[cur_char_index];
        }        
        cur_char_index++;

        while(cur_char != ']'){
            return_str = return_str + result_str[cur_char_index];
            cur_char_index++;
            cur_char = result_str[cur_char_index];
        }


        // 返回
        return return_str;
    }else{
        return "";
    }
}
